
package com.basic.business.unIndicators.service.impl;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.read.listener.ReadListener;
import cn.idev.excel.util.ListUtils;
import com.basic.business.goodsIndicators.domain.TGoodsIndicators;
import com.basic.business.indicatorsFile.service.ITIndicatorsFileService;
import com.basic.business.unIndicators.domain.TUnboundedIndicators;
import com.basic.business.unIndicators.dto.TUnboundedIndicatorsDto;
import com.basic.business.unIndicators.mapper.TUnboundedIndicatorsMapper;
import com.basic.business.unIndicators.service.ITUnboundedIndicatorsService;
import com.basic.business.wholeIndicators.domain.TWholeStationIndicators;
import com.basic.common.core.service.impl.BaseServiceImpl;
import com.basic.common.utils.SecurityUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.security.Security;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static cn.idev.excel.support.ExcelTypeEnum.CSV;

/**
 * 无界指标数据Service业务层处理
 *
 * @author zhaoxy_jn@163.com
 */
@Service
public class TUnboundedIndicatorsServiceImpl extends BaseServiceImpl<TUnboundedIndicatorsMapper,TUnboundedIndicators> implements ITUnboundedIndicatorsService {

    @Resource
    private TUnboundedIndicatorsMapper tUnboundedIndicatorsMapper;

    @Resource
    private ITIndicatorsFileService itIndicatorsFileService;

    @Override
    public int deleteByFileId(String fileId) {
        return tUnboundedIndicatorsMapper.deleteByFileId(fileId);
    }

    @Override
    public int saveBatch(List<TUnboundedIndicators> list) {
        return tUnboundedIndicatorsMapper.saveBatch(list);
    }

    @Override
    public int deleteOldData(String fileId, String storeId, Date statDate, List<String> mainBodyIdList) {
        return tUnboundedIndicatorsMapper.deleteOldData(fileId, storeId, statDate, mainBodyIdList);
    }

    @Override
    public List<TUnboundedIndicators> getListByMainBodyId(String mainBodyId) {
        return tUnboundedIndicatorsMapper.getListByMainBodyId(mainBodyId);
    }

    @Override
    public int deleteByGoodsId(List<TGoodsIndicators> goodsList) {
        return tUnboundedIndicatorsMapper.deleteByGoodsId(goodsList);
    }

    @Transactional
    @Override
    public void uploadIndicatorsData(MultipartFile file, Date selectDate, String unStoreId, String fileHash) {
        //文件上传
        String fileId = itIndicatorsFileService.uploadIndicatorsFile(file, selectDate, unStoreId, fileHash, 4);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

        try {
            EasyExcel.read(file.getInputStream(), TUnboundedIndicatorsDto.class, new ReadListener<TUnboundedIndicatorsDto>(){


                /**
                 * 单次缓存的数据量
                 */
                public static final int BATCH_COUNT = 500;

                /**
                 *临时存储
                 */
                private List<TUnboundedIndicators> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

                /**
                 * 解析调用
                 * @param data
                 * @param analysisContext
                 */
                @Override
                public void invoke(TUnboundedIndicatorsDto data, AnalysisContext analysisContext) {
                    TUnboundedIndicators tUnboundedIndicators = new TUnboundedIndicators();
                    tUnboundedIndicators.setId(null);
                    tUnboundedIndicators.setStoreId(unStoreId);
                    tUnboundedIndicators.setFileId(fileId);

                    String stringDate = data.getStatDate();
                    // 提取第一个日期部分
                    String firstDateStr = stringDate.split("至")[0];
                    // 将字符串解析为LocalDate
                    LocalDate localDate = LocalDate.parse(firstDateStr, formatter);
                    // 将LocalDate转换为Date
                    Date stateDate = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

                    tUnboundedIndicators.setStatDate(stateDate);
                    tUnboundedIndicators.setSceneId(Integer.valueOf(data.getSceneId()));
                    tUnboundedIndicators.setSceneName(data.getSceneName());
                    tUnboundedIndicators.setOriginalSceneId(Integer.valueOf(data.getOriginalSceneId()));
                    tUnboundedIndicators.setOriginalSceneName(data.getOriginalSceneName());
                    tUnboundedIndicators.setPlanId(data.getPlanId());
                    tUnboundedIndicators.setPlanName(data.getPlanName());
                    tUnboundedIndicators.setUnitId(data.getUnitId());
                    tUnboundedIndicators.setUnitName(data.getUnitName());
                    tUnboundedIndicators.setMainBodyId(data.getMainBodyId());
                    tUnboundedIndicators.setMainBodyType(data.getMainBodyType());
                    tUnboundedIndicators.setMainBodyName(data.getMainBodyName());
                    tUnboundedIndicators.setImpressions(convertField(data.getImpressions())?0:Integer.parseInt(data.getImpressions().replace(",","")));
                    tUnboundedIndicators.setClickNumber(convertField(data.getClickNumber())?0:Integer.parseInt(data.getClickNumber().replace(",","")));
                    tUnboundedIndicators.setSpend(convertField(data.getSpend())? BigDecimal.valueOf(0) :new BigDecimal(data.getSpend().replace(",","")));
                    tUnboundedIndicators.setClickRatio(convertField(data.getClickRatio())? String.valueOf(0) :data.getClickRatio());
                    tUnboundedIndicators.setAverageClickSpend(convertField(data.getAverageClickSpend())? BigDecimal.valueOf(0) :new BigDecimal(data.getAverageClickSpend().replace(",","")));
                    tUnboundedIndicators.setThousandShowSpend(convertField(data.getThousandShowSpend())? BigDecimal.valueOf(0) :new BigDecimal(data.getThousandShowSpend().replace(",","")));
                    tUnboundedIndicators.setTotalPresaleAmount(convertField(data.getTotalPresaleAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalPresaleAmount().replace(",","")));
                    tUnboundedIndicators.setTotalPresaleNumber(convertField(data.getTotalPresaleNumber())?0:Integer.parseInt(data.getTotalPresaleNumber().replace(",","")));
                    tUnboundedIndicators.setDirectPresaleAmount(convertField(data.getDirectPresaleAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getDirectPresaleAmount().replace(",","")));
                    tUnboundedIndicators.setDirectPresaleNumber(convertField(data.getDirectPresaleNumber())?0:Integer.parseInt(data.getDirectPresaleNumber().replace(",","")));
                    tUnboundedIndicators.setIndirectPresaleAmount(convertField(data.getIndirectPresaleAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getIndirectPresaleAmount().replace(",","")));
                    tUnboundedIndicators.setIndirectPresaleNumber(convertField(data.getIndirectPresaleNumber())?0:Integer.parseInt(data.getIndirectPresaleNumber().replace(",","")));
                    tUnboundedIndicators.setDirectAmount(convertField(data.getDirectAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getDirectAmount().replace(",","")));
                    tUnboundedIndicators.setIndirectAmount(convertField(data.getIndirectAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getIndirectAmount().replace(",","")));
                    tUnboundedIndicators.setTotalAmount(convertField(data.getTotalAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalAmount().replace(",","")));
                    tUnboundedIndicators.setTotalNumber(convertField(data.getTotalNumber())?0:Integer.parseInt(data.getTotalNumber().replace(",","")));
                    tUnboundedIndicators.setDirectNumber(convertField(data.getDirectNumber())?0:Integer.parseInt(data.getDirectNumber().replace(",","")));
                    tUnboundedIndicators.setIndirectNumber(convertField(data.getIndirectNumber())?0:Integer.parseInt(data.getIndirectNumber().replace(",","")));
                    tUnboundedIndicators.setClickConversionRate(convertField(data.getClickConversionRate())? String.valueOf(0) :data.getClickConversionRate());
                    tUnboundedIndicators.setInputOutputRatio(convertField(data.getInputOutputRatio())?0:Double.parseDouble(data.getInputOutputRatio()));
                    tUnboundedIndicators.setTotalTransactionCost(convertField(data.getTotalTransactionCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalTransactionCost().replace(",","")));
                    tUnboundedIndicators.setTotalShopCartNumber(convertField(data.getTotalShopCartNumber())?0:Integer.parseInt(data.getTotalShopCartNumber().replace(",","")));
                    tUnboundedIndicators.setDirectShopCartNumber(convertField(data.getDirectShopCartNumber())?0:Integer.parseInt(data.getDirectShopCartNumber().replace(",","")));
                    tUnboundedIndicators.setIndirectShopCartNumber(convertField(data.getIndirectShopCartNumber())?0:Integer.parseInt(data.getIndirectShopCartNumber().replace(",","")));
                    tUnboundedIndicators.setAddPurchaseRatio(convertField(data.getAddPurchaseRatio())? String.valueOf(0) :data.getAddPurchaseRatio());
                    tUnboundedIndicators.setCollectGoodsNumber(convertField(data.getCollectGoodsNumber())?0:Integer.parseInt(data.getCollectGoodsNumber().replace(",","")));
                    tUnboundedIndicators.setCollectStoreNumber(convertField(data.getCollectStoreNumber())?0:Integer.parseInt(data.getCollectStoreNumber().replace(",","")));
                    tUnboundedIndicators.setStoreCollectCost(convertField(data.getStoreCollectCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getStoreCollectCost().replace(",","")));
                    tUnboundedIndicators.setTotalCollectAddNumber(convertField(data.getTotalCollectAddNumber())?0:Integer.parseInt(data.getTotalCollectAddNumber().replace(",","")));
                    tUnboundedIndicators.setTotalCollectAddCost(convertField(data.getTotalCollectAddCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalCollectAddCost().replace(",","")));
                    tUnboundedIndicators.setGoodsCollectAddNumber(convertField(data.getGoodsCollectAddNumber())?0:Integer.parseInt(data.getGoodsCollectAddNumber().replace(",","")));
                    tUnboundedIndicators.setGoodsCollectAddCost(convertField(data.getGoodsCollectAddCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getGoodsCollectAddCost().replace(",","")));
                    tUnboundedIndicators.setTotalCollectNumber(convertField(data.getTotalCollectNumber())?0:Integer.parseInt(data.getTotalCollectNumber().replace(",","")));
                    tUnboundedIndicators.setGoodsCollectCost(convertField(data.getGoodsCollectCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getGoodsCollectCost().replace(",","")));
                    tUnboundedIndicators.setGoodsCollectRatio(convertField(data.getGoodsCollectRatio())? 0 : Double.parseDouble(data.getGoodsCollectRatio()));
                    tUnboundedIndicators.setAddPurchaseCost(convertField(data.getAddPurchaseCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getAddPurchaseCost().replace(",","")));
                    tUnboundedIndicators.setOrderNumber(convertField(data.getOrderNumber())?0:Integer.parseInt(data.getOrderNumber().replace(",","")));
                    tUnboundedIndicators.setOrderAmount(convertField(data.getOrderAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getOrderAmount().replace(",","")));
                    tUnboundedIndicators.setDirectCollectGoodsNumber(convertField(data.getDirectCollectGoodsNumber())?0:Integer.parseInt(data.getDirectCollectGoodsNumber().replace(",","")));
                    tUnboundedIndicators.setIndirectCollectGoodsNumber(convertField(data.getIndirectCollectGoodsNumber())?0:Integer.parseInt(data.getIndirectCollectGoodsNumber().replace(",","")));
                    tUnboundedIndicators.setCouponReceiveNumber(convertField(data.getCouponReceiveNumber())?0:Integer.parseInt(data.getCouponReceiveNumber().replace(",","")));
                    tUnboundedIndicators.setShopGoldRechargeNumber(convertField(data.getShopGoldRechargeNumber())?0:Integer.parseInt(data.getShopGoldRechargeNumber().replace(",","")));
                    tUnboundedIndicators.setShopGoldRechargeAmount(convertField(data.getShopGoldRechargeAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getShopGoldRechargeAmount().replace(",","")));
                    tUnboundedIndicators.setWangConsultNumber(convertField(data.getWangConsultNumber())?0:Integer.parseInt(data.getWangConsultNumber().replace(",","")));
                    tUnboundedIndicators.setGuideVisitNumber(convertField(data.getGuideVisitNumber())?0:Integer.parseInt(data.getGuideVisitNumber().replace(",","")));
                    tUnboundedIndicators.setGuideVisitPeopleNumber(convertField(data.getGuideVisitPeopleNumber())?0:Integer.parseInt(data.getGuideVisitPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setGuideVisitPotentialNumber(convertField(data.getGuideVisitPotentialNumber())?0:Integer.parseInt(data.getGuideVisitPotentialNumber().replace(",","")));
                    tUnboundedIndicators.setGuideVisitPotentialRatio(convertField(data.getGuideVisitPotentialRatio())? String.valueOf(0) :data.getGuideVisitPotentialRatio());
                    tUnboundedIndicators.setJoinRate(convertField(data.getJoinRate())?0:Double.parseDouble(data.getJoinRate()));
                    tUnboundedIndicators.setJoinNumber(convertField(data.getJoinNumber())?0:Integer.parseInt(data.getJoinNumber().replace(",","")));
                    tUnboundedIndicators.setGuideVisitRatio(convertField(data.getGuideVisitRatio())? String.valueOf(0) :data.getGuideVisitRatio());
                    tUnboundedIndicators.setDepthVisitNumber(convertField(data.getDepthVisitNumber())?0:Integer.parseInt(data.getDepthVisitNumber().replace(",","")));
                    tUnboundedIndicators.setAverageVisitPageNumber(convertField(data.getAverageVisitPageNumber())?0:Integer.parseInt(data.getAverageVisitPageNumber().replace(",","")));
                    tUnboundedIndicators.setDealNewOrderNumber(convertField(data.getDealNewOrderNumber())?0:Integer.parseInt(data.getDealNewOrderNumber().replace(",","")));
                    tUnboundedIndicators.setDealNewOrderTatio(convertField(data.getDealNewOrderTatio())? String.valueOf(0) :data.getDealNewOrderTatio());
                    tUnboundedIndicators.setVipFirstBuyNumber(convertField(data.getVipFirstBuyNumber())?0:Integer.parseInt(data.getVipFirstBuyNumber().replace(",","")));
                    tUnboundedIndicators.setVipDealAmount(convertField(data.getVipDealAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getVipDealAmount().replace(",","")));
                    tUnboundedIndicators.setVipDealNumber(convertField(data.getVipDealNumber())?0:Integer.parseInt(data.getVipDealNumber().replace(",","")));
                    tUnboundedIndicators.setDealPeopleNumber(convertField(data.getDealPeopleNumber())?0:Integer.parseInt(data.getDealPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setPerCapitaDealNumber(convertField(data.getPerCapitaDealNumber())?0:Integer.parseInt(data.getPerCapitaDealNumber().replace(",","")));
                    tUnboundedIndicators.setPerCapitaDealAmount(convertField(data.getPerCapitaDealAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getPerCapitaDealAmount().replace(",","")));
                    tUnboundedIndicators.setExposureNewPeopleNumber(convertField(data.getExposureNewPeopleNumber())?0:Integer.parseInt(data.getExposureNewPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setEnterNewPeopleNumber(convertField(data.getEnterNewPeopleNumber())?0:Integer.parseInt(data.getEnterNewPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setAddPurchaseNewPeopleNumber(convertField(data.getAddPurchaseNewPeopleNumber())?0:Integer.parseInt(data.getAddPurchaseNewPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setCollectNewPeopleNumber(convertField(data.getCollectNewPeopleNumber())?0:Integer.parseInt(data.getCollectNewPeopleNumber().replace(",","")));
                    tUnboundedIndicators.setNewPeoplePayAmount(convertField(data.getNewPeoplePayAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getNewPeoplePayAmount().replace(",","")));
                    tUnboundedIndicators.setNewPeopleClickRatio(convertField(data.getNewPeopleClickRatio())? String.valueOf(0) :data.getNewPeopleClickRatio());
                    tUnboundedIndicators.setNewPeopleDealConversionRate(convertField(data.getNewPeopleDealConversionRate())? String.valueOf(0) :data.getNewPeopleDealConversionRate());
                    tUnboundedIndicators.setNatureConversionAmount(convertField(data.getNatureConversionAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getNatureConversionAmount().replace(",","")));
                    tUnboundedIndicators.setNatureExposure(convertField(data.getNatureExposure())?0:Integer.parseInt(data.getNatureExposure().replace(",","")));

                    tUnboundedIndicators.setCreateTime(new Date());
                    tUnboundedIndicators.setCreateBy(SecurityUtils.getUsername());
                    tUnboundedIndicators.setUserId(SecurityUtils.getUserId());
                    tUnboundedIndicators.setDeptId(SecurityUtils.getDeptId());


                    cachedDataList.add(tUnboundedIndicators);

                    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
                    if (cachedDataList.size() >= BATCH_COUNT) {
                        //汇总需要清除的旧数据
                        List<String> deleteMainBodyIdList = cachedDataList.stream().map(TUnboundedIndicators::getMainBodyId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(fileId,unStoreId,cachedDataList.get(0).getStatDate(),deleteMainBodyIdList);
                        //存储新数据
                        saveBatch(cachedDataList);
                        // 存储完成清理 list
                        cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                    }
                }

                /**
                 * 所有数据解析完成调用
                 *
                 * @param context
                 */
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (!cachedDataList.isEmpty()){
                        //汇总需要清除的旧数据
                        List<String> deleteMainBodyIdList = cachedDataList.stream().map(TUnboundedIndicators::getMainBodyId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(fileId,unStoreId,cachedDataList.get(0).getStatDate(),deleteMainBodyIdList);
                        //存储新数据
                        saveBatch(cachedDataList);
                    }
                }
            }).excelType(CSV).charset(Charset.forName("GBK")).sheet().doRead();
        } catch (Exception e) {
            throw new RuntimeException("文件内容解析错误,文件上传失败!",e);
        }
    }

    /**
     * 判断字段
     * @param input
     * @return
     */
    public static boolean convertField(String input) {
        return input == null || input.isEmpty() || "-".equals(input);
    }
}
